home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Panorama / Panorama - Disk 19D (1987-07-22)(Pacific North-West Amigas Club)[WB].zip / Panorama - Disk 19D (1987-07-22)(Pacific North-West Amigas Club)[WB].adf / PipeHandler1.2 / pipedir.c < prev    next >
C/C++ Source or Header  |  1987-06-28  |  12KB  |  424 lines

  1. /****************************************************************************
  2. **  File:       pipedir.c
  3. **  Program:    pipe-handler - an AmigaDOS handler for named pipes
  4. **  Version:    1.2
  5. **  Author:     Ed Puckett      qix@mit-oz
  6. **
  7. **  Copyright 1987 by EpAc Software.  All Rights Reserved.
  8. **
  9. **  History:    05-Jan-87       Original Version (1.0)
  10. **        07-Feb-87    Added modifications for allowing shared locks
  11. **                 on individual pipes.
  12. **        12-Feb-87    Added PipeParentDir.
  13. **        12-Feb-87    Fixed bug in PipeLock(): previously ignored
  14. **                 lock passed in packet.  Bug uncovered when
  15. **                 pipes became lockable, and thus assignable.
  16. **        27-Mar-87    Added PipeDupLock().  This was missing
  17. **                 in the original version!
  18. */
  19.  
  20. #include   <libraries/dos.h>
  21. #include   <libraries/dosextens.h>
  22. #include   <libraries/filehandler.h>
  23. #include   <exec/exec.h>
  24.  
  25. #include   "pipelists.h"
  26. #include   "pipename.h"
  27. #include   "pipebuf.h"
  28. #include   "pipecreate.h"
  29. #include   "pipesched.h"
  30. #include   "pipe-handler.h"
  31. #include   "pipedir.h"
  32.  
  33.  
  34.  
  35. /*---------------------------------------------------------------------------
  36. ** pipedir.c
  37. ** ---------
  38. ** This module handles the directory-related requests to the handler.
  39. ** The functions contained here are not needed if the compile-time flag
  40. ** PIPEDIR is false.
  41. **
  42. ** Visible Functions
  43. ** -----------------
  44. **    void  SetPipeDate (pipe)
  45. **    void  PipeLock    (pkt)
  46. **    void  PipeDupLock (pkt)
  47. **    void  PipeUnLock  (pkt)
  48. **    void  PipeExamine (pkt)
  49. **    void  PipeExNext  (pkt)
  50. **    void  InitLock    (lock, key)
  51. **
  52. ** Macros (in pipedir.h)
  53. ** ---------------------
  54. **    - none -
  55. **
  56. ** Local Functions
  57. ** ---------------
  58. **    void  InitPipedirLock ()
  59. **    void  FillFIB (fib, DiskKey, FileName, Protection, Type, Size, NumBlocks, Datep)
  60. */
  61.  
  62.  
  63.  
  64. /*---------------------------------------------------------------------------
  65. ** "PipedirLock" is the lock returned by PipeLock() to clients requesting a
  66. ** shared lock on the handler.  "LockBytes" is used for the storage of the
  67. ** lock.  InitLock() sets "PipedirLock" to point to the first longword within
  68. ** "LockBytes" to ensure longword alignment for BCPL's sake.
  69. */
  70.  
  71. static BYTE             LockBytes[sizeof (struct FileLock) + 3];
  72. static struct FileLock  *PipedirLock  =  NULL;
  73.  
  74.  
  75.  
  76. /*---------------------------------------------------------------------------
  77. ** SetPipeDate() modifies the date field for the pipe sent.  If the compile-
  78. ** time flag UPDATE_PIPEDATE is true (see pipe-handler.h), the handler's date
  79. ** is modified as well.
  80. */
  81.  
  82. void  SetPipeDate (pipe)
  83.  
  84. PIPEDATA  *pipe;
  85.  
  86. { (void) DateStamp (&pipe->accessdate);
  87.  
  88. #if UPDATE_PIPEDATE
  89.   (void) DateStamp (&PipeDate);
  90. #endif UPDATE_PIPEDATE
  91. }
  92.  
  93.  
  94.  
  95. /*---------------------------------------------------------------------------
  96. ** PipeLock() responds to Lock requests.  Only multiple access locks are
  97. ** granted.  The same lock is returned to all clients for a given entity.
  98. **      Note: the code which checks if the lock sent in the packet relies on
  99. ** the fact that the pipe-handler does not allow subdirectories.  If a lock
  100. ** on a pipe is passed in, then that pipe is opened.  Otherwise, the name is
  101. ** parsed without reference to the lock.
  102. */
  103.  
  104. void  PipeLock (pkt)
  105.  
  106. struct DosPacket  *pkt;
  107.  
  108. { char             *name, *tapname;
  109.   ULONG            size;
  110.   struct FileLock  *lock;
  111.   PIPEDATA         *pipe;
  112.   void             InitPipedirLock();
  113.  
  114.  
  115.   InitPipedirLock ();
  116.  
  117.   pkt->dp_Res1= 0;     /* error, for now */
  118.   pkt->dp_Res2= 0;     /* clear for case of no error */
  119.  
  120.   lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1);
  121.  
  122.   if (pkt->dp_Arg3 != SHARED_LOCK)
  123.     { pkt->dp_Res2= ERROR_OBJECT_WRONG_TYPE;
  124.       goto PLOCKEXIT;
  125.     }
  126.  
  127.   if (! ParsePipeName (BPTRtoCptr (pkt->dp_Arg2), &name, &size, &tapname))
  128.     { pkt->dp_Res2= ERROR_INVALID_COMPONENT_NAME;
  129.       goto PLOCKEXIT;
  130.     }
  131.  
  132.   if ( (lock == NULL) || ((pipe= (PIPEDATA *) lock->fl_Key) == NULL) )
  133.     { if (name[0] == '\0')
  134.         pkt->dp_Res1= CptrtoBPTR (PipedirLock);
  135.       else
  136.         { if ((pipe= FindPipe (name)) == NULL)
  137.             { pkt->dp_Res2= ERROR_OBJECT_NOT_FOUND;
  138.               goto PLOCKEXIT;
  139.             }
  140.  
  141.           pkt->dp_Res1= CptrtoBPTR (pipe->lock);
  142.           ++pipe->lockct;
  143.         }
  144.     }
  145.   else     /* lock sent in packet was on the pipe */
  146.     { if (name[0] != '\0')
  147.         { pkt->dp_Res2= ERROR_INVALID_COMPONENT_NAME;
  148.           goto PLOCKEXIT;
  149.         }
  150.  
  151.       pkt->dp_Res1= CptrtoBPTR (pipe->lock);
  152.       ++pipe->lockct;
  153.     }
  154.  
  155. PLOCKEXIT:
  156.   ReplyPkt (pkt);
  157. }
  158.  
  159.  
  160.  
  161. /*---------------------------------------------------------------------------
  162. ** PipeDupLock() responds to DupLock requests.  It is assumed that the lock
  163. ** sent is valid.  The same lock is returned; the only action taken is to
  164. ** increment the lock count if the lock is on an individual pipe.  If the
  165. ** zero lock is sent, the zero lock is (properly) returned, even though this
  166. ** handler should never receive that request.  Notice that this routine never
  167. ** returns an error.
  168. */
  169.  
  170. void  PipeDupLock (pkt)
  171.  
  172. struct DosPacket  *pkt;
  173.  
  174. { struct FileLock  *lock;
  175.   PIPEDATA         *pipe;
  176.  
  177.  
  178.   pkt->dp_Res1= pkt->dp_Arg1;     /* reuse same structure */
  179.   pkt->dp_Res2= 0;
  180.  
  181.   if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) != NULL)
  182.     { if ((pipe= (PIPEDATA *) lock->fl_Key) != NULL)
  183.         ++pipe->lockct;     /* lock is on an individual pipe */
  184.     }
  185.  
  186.   ReplyPkt (pkt);
  187. }
  188.  
  189.  
  190.  
  191. /*---------------------------------------------------------------------------
  192. ** PipeUnLock() responds to UnLock requests.
  193. */
  194.  
  195. void  PipeUnLock (pkt)
  196.  
  197. struct DosPacket  *pkt;
  198.  
  199. { struct FileLock  *lock;
  200.   PIPEDATA         *pipe;
  201.  
  202.  
  203.   if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
  204.     { pkt->dp_Res1= 0;
  205.       pkt->dp_Res2= ERROR_INVALID_LOCK;
  206.     }
  207.   else
  208.     { if ((pipe= (PIPEDATA *) lock->fl_Key) != NULL)
  209.         { --pipe->lockct;
  210.           CheckWaiting (pipe);     /* will discard if totally unused */
  211.         }
  212.  
  213.       pkt->dp_Res1= 1;     /* no error */
  214.       pkt->dp_Res2= 0;
  215.     }
  216.  
  217.   ReplyPkt (pkt);
  218. }
  219.  
  220.  
  221.  
  222. /*---------------------------------------------------------------------------
  223. ** PipeExamine() responds to Examine requests.  For locks on the handler, the
  224. ** address first item of the pipelist is stored in the DiskKey field for
  225. ** PipeExNext()'s reference.
  226. */
  227.  
  228. void  PipeExamine (pkt)
  229.  
  230. struct DosPacket  *pkt;
  231.  
  232. { struct FileInfoBlock  *fib;
  233.   struct FileLock       *lock;
  234.   PIPEDATA              *pipe;
  235.   void                  FillFIB();
  236.  
  237.  
  238.   pkt->dp_Res1= 1;     /* no error, for now */
  239.   pkt->dp_Res2= 0;
  240.  
  241.   fib= (struct FileInfoBlock *) BPTRtoCptr (pkt->dp_Arg2);
  242.  
  243.   if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
  244.     { pkt->dp_Res1= 0;
  245.       pkt->dp_Res2= ERROR_OBJECT_NOT_FOUND;
  246.     }
  247.   else
  248.     { if ((pipe= (PIPEDATA *) lock->fl_Key) == NULL)     /* then this is a lock on the handler */
  249.         { FillFIB ( fib, FirstItem (&pipelist), HandlerName,
  250.                     (FIBF_EXECUTE | FIBF_DELETE), 1,
  251.                     0, 0, &PipeDate );
  252.         }
  253.       else
  254.         { FillFIB ( fib, NULL, pipe->name,
  255.                     (FIBF_EXECUTE | FIBF_DELETE), -1,
  256.                     pipe->buf->len, 1, &pipe->accessdate );
  257.         }
  258.     }
  259.  
  260.   ReplyPkt (pkt);
  261. }
  262.  
  263.  
  264.  
  265. /*---------------------------------------------------------------------------
  266. ** PipeExNext() responds to ExNext requests.  The DiskKey field of the
  267. ** FileInfoBlock is assumed to be a pointer to the next pipe in the pipelist
  268. ** which is to  be listed in the directory.  We then scan pipelist for this
  269. ** pointer, and upon finding it, store its information in the FileInfoBlock
  270. ** and store the address of the next pipe in pipelist in the DiskKey field.
  271. ** If the pipe is not found in the list, or if DiskKey is NULL, then
  272. ** ERROR_NO_MORE_ENTRIES is returned.
  273. **      By rescanning the list each time, deletion of a pipe cannot hurt us
  274. ** by causing a dangling pointer in DiskKey -- we just end the directory
  275. ** listing there.  This can cause incomplete directory information for the
  276. ** cleint, however, if the last listed pipe is deleted before the client's
  277. ** next ExNext() call.
  278. */
  279.  
  280. void  PipeExNext (pkt)
  281.  
  282. struct DosPacket  *pkt;
  283.  
  284. { struct FileLock       *lock;
  285.   struct FileInfoBlock  *fib;
  286.   PIPEDATA              *listitem, *pipe;
  287.   void                  FillFIB();
  288.  
  289.  
  290.   pkt->dp_Res1= 0;     /* error, for now */
  291.  
  292.   if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
  293.     { pkt->dp_Res2= ERROR_INVALID_LOCK;
  294.       goto EXNEXTREPLY;
  295.     }
  296.  
  297.   if (lock->fl_Key != NULL)     /* then an individual pipe */
  298.     { pkt->dp_Res2= ERROR_OBJECT_WRONG_TYPE;
  299.       goto EXNEXTREPLY;
  300.     }
  301.  
  302.   pkt->dp_Res2= ERROR_NO_MORE_ENTRIES;     /* until found otherwise */
  303.  
  304.   fib= (struct FileInfoBlock *) BPTRtoCptr (pkt->dp_Arg2);
  305.  
  306.   if ((listitem= (PIPEDATA *) fib->fib_DiskKey) == NULL)
  307.     goto EXNEXTREPLY;
  308.  
  309.  
  310.   for (pipe= (PIPEDATA *) FirstItem (&pipelist); pipe != NULL; pipe= (PIPEDATA *) NextItem (pipe))
  311.     if (listitem == pipe)
  312.       break;
  313.  
  314.   if (listitem == pipe)     /* then found next entry */
  315.     { FillFIB ( fib, NextItem (listitem), listitem->name,
  316.                 (FIBF_EXECUTE | FIBF_DELETE), -1,
  317.                 listitem->buf->len, 1, &listitem->accessdate );
  318.  
  319.       pkt->dp_Res1= 1;
  320.       pkt->dp_Res2= 0;
  321.     }
  322.  
  323. EXNEXTREPLY:
  324.   ReplyPkt (pkt);
  325. }
  326.  
  327.  
  328.  
  329. /*---------------------------------------------------------------------------
  330. ** PipeParentDir() responds to ParentDir requests.
  331. */
  332.  
  333. void  PipeParentDir (pkt)
  334.  
  335. struct DosPacket  *pkt;
  336.  
  337. { struct FileLock  *lock;
  338.   void             InitPipedirLock();
  339.  
  340.  
  341.   InitPipedirLock ();
  342.  
  343.   pkt->dp_Res2= 0;
  344.  
  345.   if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
  346.     { pkt->dp_Res1= 0;
  347.       pkt->dp_Res2= ERROR_INVALID_LOCK;
  348.     }
  349.   else
  350.     { if (lock->fl_Key == NULL)     /* then lock is on handler */
  351.         pkt->dp_Res1= 0;     /* root of current filing system */
  352.       else
  353.         pkt->dp_Res1= CptrtoBPTR (PipedirLock);
  354.     }
  355.  
  356.   ReplyPkt (pkt);
  357. }
  358.  
  359.  
  360.  
  361. /*---------------------------------------------------------------------------
  362. */
  363.  
  364. static void  InitPipedirLock ()
  365.  
  366. { if (PipedirLock == NULL)
  367.     { PipedirLock= (struct FileLock *) (((ULONG) LockBytes + 3) & ((~0)<<2));
  368.       InitLock (PipedirLock, NULL);
  369.     }
  370. }
  371.  
  372.  
  373.  
  374. /*---------------------------------------------------------------------------
  375. ** InitLock() initializes locks returned to clients by PipeLock().  For locks
  376. ** on individual pipes, the "fl_Key" field points to the associated pipe's
  377. ** PIPEDATA structure.  For the handler, the "fl_Key" field is NULL.
  378. */
  379.  
  380. void  InitLock (lock, key)
  381.  
  382. struct FileLock  *lock;
  383. LONG             key;
  384.  
  385. { lock->fl_Link=   0;
  386.   lock->fl_Key=    key;
  387.   lock->fl_Access= SHARED_LOCK;              /* only mode allowed */
  388.   lock->fl_Task=   PipePort;                 /* set during handler init */
  389.   lock->fl_Volume= CptrtoBPTR (DevNode);     /* also set during init */
  390. }
  391.  
  392.  
  393.  
  394. /*---------------------------------------------------------------------------
  395. ** FillFIB() fills a FileInfoBlock with the specified information.  Note
  396. ** that handlers must store BSTR's in the FileInfoBlock.
  397. */
  398.  
  399. static void  FillFIB (fib, DiskKey, FileName, Protection, Type, Size, NumBlocks, Datep)
  400.  
  401. struct FileInfoBlock  *fib;
  402. LONG                  DiskKey;
  403. char                  *FileName;     /* null-terminated */
  404. LONG                  Protection;
  405. LONG                  Type;
  406. LONG                  Size;
  407. LONG                  NumBlocks;
  408. struct DateStamp      *Datep;
  409.  
  410. { fib->fib_DiskKey=      DiskKey;
  411.   fib->fib_DirEntryType= Type;
  412.  
  413.   CstrtoBSTR (FileName, fib->fib_FileName, sizeof (fib->fib_FileName));
  414.  
  415.   fib->fib_Protection=   Protection;
  416.   fib->fib_EntryType=    Type;     /* ??? */
  417.   fib->fib_Size=         Size;
  418.   fib->fib_NumBlocks=    NumBlocks;
  419.  
  420.   CopyMem (Datep, &fib->fib_Date, sizeof (struct DateStamp));
  421.  
  422.   fib->fib_Comment[0]= '\0';     /* empty BSTR */
  423. }
  424.